﻿#region Creditos

/* Autor: Edilberto Sánchez Forero	*/
/* Email: esanchezfo@gmail.com		*/
/* Licencia: LGPL, Software Libre	*/
/* País: Colombia, Bogotá			*/

#endregion

#region Librerias

using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Collections.Specialized;
using System.IO;
using System.Linq;

using ESF.General.Text;
using ESF.General.Entity;
using System.Globalization;
using System.IO.Compression;
using System.Text.RegularExpressions;
using System.Reflection;

#endregion


namespace ESF.General
{
	public static class TextHelper
	{
		#region XLS

		public const string XLSHTMLHEADER = 
			@"<html xmlns:v=""urn:schemas-microsoft-com:vml"" xmlns:o=""urn:schemas-microsoft-com:office:office"" xmlns:x=""urn:schemas-microsoft-com:office:excel"" xmlns=""http://www.w3.org/TR/REC-html40"">
				<head>
					<meta http-equiv=""Content-Type"" content=""text/html; charset=windows-1252"" />
					<meta name=""ProgId"" content=""Excel.Sheet"" />
					<meta name=""Generator"" content=""Microsoft Excel 12"" />
				</head><body><table border=""1"" bordercolor""#CACACA"">";

		#endregion


		#region Alfabeto

		public enum Alphabet
		{
			A,
			B,
			C,
			D,
			E,
			F,
			G,
			H,
			I,
			J,
			K,
			L,
			M,
			N,
			Ñ,
			O,
			P,
			Q,
			R,
			S,
			T,
			U,
			V,
			W,
			X,
			Y,
			Z
		}

		#endregion


		#region Constantes de Formato

		public const string DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
		public const string DEFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
		public const string DEFAULT_DATETIME_LONGFORMAT = "yyyy-MM-dd hh:mm:ss tt";

		#endregion


		#region Constantes de Longitudes

		public const byte GUID_LENGTH = 16;
		public const byte BYTE_MAXLENGTH = 3;
		public const byte SBYTE_MAXLENGTH = 4;
		public const byte UINT16_MAXLENGTH = 5;
		public const byte UINT32_MAXLENGTH = 10;
		public const byte UINT64_MAXLENGTH = 18;
		public const byte INT16_MAXLENGTH = 6;
		public const byte INT32_MAXLENGTH = 11;
		public const byte INT64_MAXLENGTH = 19;
		public const byte DATE_LENGTH = 10;
		public const byte DATETIME_LENGTH = 19;
		public const byte DOUBLE_MAXLENGTH = 20;
		public const byte FLOAT_MAXLENGTH = 20;
		public const byte DECIMAL_MAXLENGTH = 30;

		#endregion
		
		
		#region Constantes de Expresiones Regulares de Uso Comun

		public const string REGEX_Alfa = @"^[A-Za-záéíóúñÁÉÍÓÚÑ.\s\&]*$";
		public const string REGEX_AlfaNumeric = @"^[A-Za-záéíóúñÁÉÍÓÚÑ.\s\&0-9]*$";
		public const string REGEX_Email = @"^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$";
		public const string REGEX_URL = @"^((?#protocol)https?|ftp)://((?#domain)[-A-Za-z0-9.]+)((?#file)/[-A-Za-z0-9+&amp;@#/%=~_|!:,.;]*)?((?#parameters)\?[A-Za-z0-9+&amp;@#/%=~_|!:,.;]*)?$";
		public const string REGEX_Percentage = @"^(\d{1,3})(?:\.(\d{0,2}))?$";
		public const string REGEX_Name = @"[A-Za-záéíóúñÁÉÍÓÚÑ&\s]*";

		public const string REGEX_Byte = @"^\d{1,3}$";
		public const string REGEX_SByte = @"^(-)*\d{1,3}$";
		public const string REGEX_Int16 = @"^(-)*\d{1,5}$";
		public const string REGEX_UInt16 = @"^\d{1,5}$";
		public const string REGEX_Int32 = @"^(-)*\d{1,10}$";
		public const string REGEX_UInt32 = @"^\d{1,10}$";
		public const string REGEX_Int64 = @"^(-)*\d{1,18}$";
		public const string REGEX_UInt64 = @"^\d{1,18}$";

		public const string REGEX_Bool = @"(true|false)";

		public const string REGEX_Guid = @"^\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-Z0-9]{12}\b|\(\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-Z0-9]{12}\b\)|{\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-Z0-9]{12}\b}$";

		public const string REGEX_Date = @"^-?([1-9][0-9]*)?[0-9]{4}-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])(Z|[+-](2[0-3]|[0-1][0-9]):[0-5][0-9])?$";
		public const string REGEX_DateTime = @"^-?([1-9][0-9]*)?[0-9]{4}-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])T(2[0-3]|[0-1][0-9]):[0-5][0-9]:[0-5][0-9](\.[0-9]+)?(Z|[+-](2[0-3]|[0-1][0-9]):[0-5][0-9])?$";
		public const string REGEX_Time = @"^([0-1][0-9]|[2][0-3])([0-5][0-9])$";
		public const string REGEX_TimeWithSep = @"^([0-1][0-9]|[2][0-3]):([0-5][0-9])$";

		public static readonly string REGEX_Double = @"^(-)?(\d{1,19})(?:\" + Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyDecimalSeparator + @"(\d{0,29}))?$";
		public static readonly string REGEX_Float = @"^(-)?(\d{1,19})(?:\" + Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyDecimalSeparator + @"(\d{0,29}))?$";

		public const string REGEX_Decimal = @"^(-)?(\d{1,29})(?:\.(\d{0,29}))?$";

		#endregion
	
	
		#region Constantes de Listas de Texto
		
		public static byte [] NEWLINE_BYTES = Encoding.ASCII.GetBytes (Environment.NewLine);

		public static string [] ALPHABETWITHENIE = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "Ñ", "O", "P", "Q", "R", "Z", "T", "U", "V", "W", "X", "Y", "Z" };

		public static string [] ALPHABET = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "Z", "T", "U", "V", "W", "X", "Y", "Z" };

		private const string ES_CHOOSEALLITEM = "Todos";		
		//private const string EN_CHOOSEALLITEM = "All";
		
		private const string ES_CHOOSEITEM = "- Seleccione uno -";		
		//private const string EN_CHOOSEITEM = "- Choose one -";
		
        private const string ES_CHOOSEITEM_APPCONFKEY = "ESF.General.Text.ES_CHOOSEITEM";
        //private const string EN_CHOOSEITEM_APPCONFKEY = "ESF.General.Text.ESF.EN_CHOOSEITEM";
		
		private const string ES_CHOOSEITEMYEAR = "- Año -";
		//private const string EN_CHOOSEITEMYEAR = "- Year -";
		
		private const string ES_CHOOSEITEMMONTH = "- Mes -";		
		//private const string EN_CHOOSEITEMMONTH = "- Month -";
		
		private const string ES_CHOOSEITEMDAY = "- Día -";		
		//private const string EN_CHOOSEITEMDAY = "- Day -";
		
		
		public static readonly string [] ES_MONTHLIST = 
		{
			"Enero", "1",		"Febrero", "2",			"Marzo", "3",
			"Abril", "4",		"Mayo", "5",			"Junio", "6",
			"Julio", "7",		"Agosto", "8",			"Septiembre", "9",
			"Octubre", "10",	"Noviembre", "11",		"Diciembre", "12"
		};
			
		//public static readonly string [] EN_MONTHLIST = 
		//{
		//    "January", "1",		"February", "2",	"March", "3",
		//    "April", "4",		"May", "5",			"June", "6",
		//    "July", "7",		"August", "8",		"September", "9",
		//    "October", "10",	"November", "11",	"December", "12"
		//};
		
		public static readonly string [] ES_TRIMESTERMONTHLIST = 
		{
			"Marzo", "3",
			"Junio", "6",
			"Septiembre", "9",
			"Diciembre", "12"
		};
			
		//public static readonly string [] EN_TRIMESTERMONTHLIST = 
		//{
		//    "March", "3",
		//    "June", "6",
		//    "September", "9",
		//    "December", "12"
		//};
		
		
		//public static string [] YESNO_EN = new string[] {"Yes", "True", "No", "False"};
		
		public static string [] YESNO_ES = new string[] {"Si", bool.TrueString, "No", bool.FalseString};
		
		
		public static string [] GeneralYESNOList
		{
			get
			{
				//switch (Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName)
				//{
				//    case "es":
						return YESNO_ES;
				//    default:
				//        return YESNO_EN;
				//}
			}
		}
		
		
		public const string LoadingMessage_ES = "Procesando su solicitud...";
		
		//public const string LoadingMessage_EN = "Processing your request...";
		
		
		public static string LoadingMessage
		{
			get
			{
				//switch (Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName)
				//{
				//    case "es":
						return LoadingMessage_ES;
				//    default:
				//        return LoadingMessage_EN;
				//}
			}
		}
		
		#endregion
		

		#region Limpieza de Caracteres especiales no ASCII

		public static string RemoveNonASCII (string pContents)
		{
			return Regex.Replace (pContents, "[^\x0d\x0a\x20-\x7e\t]", "");
		}

		#endregion
		

		#region Propiedades
		
		public static string SelectOneValue = string.Empty;
		
		
		public static string GeneralSelectItemText
		{
			get
			{
				//switch (Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName)
				//{
				//    case "es":
						return ReadConfig.GetAppSetting (ES_CHOOSEITEM_APPCONFKEY,  ES_CHOOSEITEM);
					
				//    default:
				//        return ReadConfig.GetAppSetting (EN_CHOOSEITEM_APPCONFKEY,  EN_CHOOSEITEM);
				//}
			}
		}
		
		
		public static string GeneralSelectAllItemText
		{
			get
			{
				//switch (Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName)
				//{
				//    case "es":
						return ES_CHOOSEALLITEM;
					
				//    default:
				//        return EN_CHOOSEALLITEM;
				//}
			}
		}
		
		
		public static string GeneralSelectItemYearText
		{
			get
			{
				//switch (Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName)
				//{
				//    case "es":
						return ES_CHOOSEITEMYEAR;
					
				//    default:
				//        return EN_CHOOSEITEMYEAR;
				//}
			}
		}
		
		
		public static string GeneralSelectItemMonthText
		{
			get
			{
				//switch (Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName)
				//{
				//    case "es":
						return ES_CHOOSEITEMMONTH;
					
				//    default:
				//        return EN_CHOOSEITEMMONTH;
				//}
			}
		}


		public static string GeneralSelectItemDayText
		{
			get
			{
				//switch (Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName)
				//{
				//    case "es":
						return ES_CHOOSEITEMDAY;
					
				//    default:
				//        return EN_CHOOSEITEMDAY;
				//}
			}
		}
		
		
		public static List<BasicReference> YearList
		{
			get
			{
				List<BasicReference> resultado;
				
				
				resultado = new List<BasicReference> ();
				
				for (int i = ReadConfig.ListYearsStart; i < DateTime.Now.Year; i++)
				{
					resultado.Add (new BasicReference () { ID = i, Code = i.ToString (), Name = i.ToString () });
				}
				
				return resultado;
			}
		}
		
		
		public static List<BasicReference> MonthList
		{
			get
			{
				List<BasicReference> resultado;
				
				
				resultado = new List<BasicReference> ();
				
				for (int i = 0; i < GeneralMonthListText.Length; i+=2)
				{
					resultado.Add (new BasicReference () { ID = int.Parse (GeneralMonthListText [i + 1]), Code = GeneralMonthListText [i + 1], Name = GeneralMonthListText [i] });
				}
				
				return resultado;
			}
		}
		
		
		public static List<BasicReference> YESNOList
		{
			get
			{
				List<BasicReference> resultado;
				
				
				resultado = new List<BasicReference> ();
				
				for (int i = 0; i < GeneralYESNOList.Length; i+=2)
				{
					resultado.Add (new BasicReference () { Code = GeneralYESNOList [i + 1], Name = GeneralYESNOList [i] });
				}
				
				return resultado;
			}
		}

		
		public static string [] GeneralMonthListText
		{
			get
			{
				//switch (Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName)
				//{
				//    case "es": 
						return ES_MONTHLIST;
					
				//    default:
				//        return EN_MONTHLIST;
				//}
			}
		}
		
		
		public static string [] GeneralTrimesterMonthListText
		{
			get
			{
				//switch (Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName)
				//{
				//    case "es": 
						return ES_TRIMESTERMONTHLIST;
					
				//    default:
				//        return EN_TRIMESTERMONTHLIST;
				//}
			}
		}
		
		#endregion
		
		
		#region Cadenas de espacios Generales
		
		public const string NL_1_TAB = "\n\t";
		public const string NL_2_TAB = NL_1_TAB + "\t";
		public const string NL_3_TAB = NL_2_TAB + "\t";
		public const string NL_4_TAB = NL_3_TAB + "\t";
		public const string NL_5_TAB = NL_4_TAB + "\t";
		public const string NL_6_TAB = NL_5_TAB + "\t";
		public const string NL_7_TAB = NL_6_TAB + "\t";
		
		public const string TAB_1 = "\t";
		public const string TAB_2 = TAB_1 + "\t";
		public const string TAB_3 = TAB_2 + "\t";
		public const string TAB_4 = TAB_3 + "\t";
		public const string TAB_5 = TAB_4 + "\t";
		public const string TAB_6 = TAB_5 + "\t";
		public const string TAB_7 = TAB_6 + "\t";
		
		#endregion
	
	
		#region Cadenas de espacios para Corchetes
		
		public const string NL_CO = "\n{" + NL_1_TAB;
		public const string NL_1_TAB_CO = NL_1_TAB + "{" + NL_2_TAB;
		public const string NL_2_TAB_CO = NL_2_TAB + "{" + NL_3_TAB;
		public const string NL_3_TAB_CO = NL_3_TAB + "{" + NL_4_TAB;
		public const string NL_4_TAB_CO = NL_4_TAB + "{" + NL_5_TAB;
		public const string NL_5_TAB_CO = NL_5_TAB + "{" + NL_6_TAB;
		public const string NL_6_TAB_CO = NL_6_TAB + "{" + NL_7_TAB;
		
		public const string NL_CC = "\n}\n";
		public const string NL_1_TAB_CC = NL_1_TAB + "}\n";
		public const string NL_2_TAB_CC = NL_2_TAB + "}\n";
		public const string NL_3_TAB_CC = NL_3_TAB + "}\n";
		public const string NL_4_TAB_CC = NL_4_TAB + "}\n";
		public const string NL_5_TAB_CC = NL_5_TAB + "}\n";
		public const string NL_6_TAB_CC = NL_6_TAB + "}\n";
	
		#endregion
		
		
		#region Cadenas de espacios para Parentesis
		
		public const string NL_PO = "\n(";
		public const string NL_1_TAB_PO = NL_1_TAB + "(";
		public const string NL_2_TAB_PO = NL_2_TAB + "(";
		public const string NL_3_TAB_PO = NL_3_TAB + "(";
		public const string NL_4_TAB_PO = NL_4_TAB + "(";
		public const string NL_5_TAB_PO = NL_5_TAB + "(";
		public const string NL_6_TAB_PO = NL_6_TAB + "(";
		
		public const string NL_PC = "\n)";
		public const string NL_1_TAB_PC = NL_1_TAB + ")";
		public const string NL_2_TAB_PC = NL_2_TAB + ")";
		public const string NL_3_TAB_PC = NL_3_TAB + ")";
		public const string NL_4_TAB_PC = NL_4_TAB + ")";
		public const string NL_5_TAB_PC = NL_5_TAB + ")";
		public const string NL_6_TAB_PC = NL_6_TAB + ")";
		
		#endregion
		
		
		#region Longitudes por tipo basico
		
		public static ushort? GetMaxLength (ValueTypes? penuValueType)
		{
			switch (penuValueType)
			{
				case ValueTypes.Byte:
					return BYTE_MAXLENGTH;
					
				case ValueTypes.SByte:
					return SBYTE_MAXLENGTH;
					
				case ValueTypes.Date:
					return DATE_LENGTH;
					
				case ValueTypes.DateTime:
					return DATETIME_LENGTH;
					
				case ValueTypes.Decimal:
					return DECIMAL_MAXLENGTH;
					
				case ValueTypes.Double:
					return DOUBLE_MAXLENGTH;
					
				case ValueTypes.Float:
					return FLOAT_MAXLENGTH;
					
				case ValueTypes.Guid:
					return GUID_LENGTH;
					
				case ValueTypes.Int16:
					return INT16_MAXLENGTH;
					
				case ValueTypes.Int32:
					return INT32_MAXLENGTH;
					
				case ValueTypes.Int64:
					return INT64_MAXLENGTH;
					
				case ValueTypes.UInt16:
					return UINT16_MAXLENGTH;
					
				case ValueTypes.UInt32:
					return UINT32_MAXLENGTH;
				
				case ValueTypes.UInt64:
					return UINT64_MAXLENGTH;
				
				default:
					return null;
			}
		}
		
		
		public static ushort? GetMaxLength (RegExTypes? penuRegExType)
		{
			switch (penuRegExType)
			{
				case RegExTypes.Byte:
					return BYTE_MAXLENGTH;
				
				case RegExTypes.Date:
					return DATE_LENGTH;
					
				case RegExTypes.DateTime:
					return DATETIME_LENGTH;
					
				case RegExTypes.Decimal:
					return DECIMAL_MAXLENGTH;
					
				case RegExTypes.Double:
					return DOUBLE_MAXLENGTH;
					
				case RegExTypes.Float:
					return FLOAT_MAXLENGTH;
					
				case RegExTypes.Guid:
					return GUID_LENGTH;
					
				case RegExTypes.Int16:
					return INT16_MAXLENGTH;
					
				case RegExTypes.Int32:
					return INT32_MAXLENGTH;
					
				case RegExTypes.Int64:
					return INT64_MAXLENGTH;
					
				case RegExTypes.SByte:
					return SBYTE_MAXLENGTH;
					
				case RegExTypes.UInt16:
					return UINT16_MAXLENGTH;
					
				case RegExTypes.UInt32:
					return UINT32_MAXLENGTH;
					
				case RegExTypes.UInt64:
					return UINT64_MAXLENGTH;
					
				default:
					return null;
			}
		}
		
		#endregion
		
		
		#region Funciones de Texto Excel

		public static string GetAlphaExcel (int pColumnNumber)
		{
			int dividend = pColumnNumber;
			string columnName = String.Empty;
			int modulo;

			while (dividend > 0)
			{
				modulo = (dividend - 1) % 26;
				columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
				dividend = (int)((dividend - modulo) / 26);
			}

			return columnName;
		}
		
		#endregion
		
		
		#region Funciones de Conversion de Texto
	
		public static string ConvertToWordsES(ulong pintValor)
		{
			return ConvertNumberToWordsESCO (pintValor).Replace ("  ", " ");
		}
		
	
		private static string ConvertNumberToWordsESCO(ulong pintValor)
		{
			string strTemp;


			switch (pintValor)
			{
				case 0: return "CERO";
				case 1: return "UN";
				case 2: return "DOS";
				case 3: return "TRES";
				case 4: return "CUATRO";
				case 5: return "CINCO";
				case 6: return "SEIS";
				case 7: return "SIETE";
				case 8: return "OCHO";
				case 9: return "NUEVE";
				case 10: return "DIEZ";
				case 11: return "ONCE";
				case 12: return "DOCE";
				case 13: return "TRECE";
				case 14: return "CATORCE";
				case 15: return "QUINCE";
				case 20: return "VEINTE";
				case 30: return "TREINTA";
				case 40: return "CUARENTA";
				case 50: return "CINCUENTA";
				case 60: return "SESENTA";
				case 70: return "SETENTA";
				case 80: return "OCHENTA";
				case 90: return "NOVENTA";
				case 100: return "CIEN";
				case 500: return "QUINIENTOS";
				case 700: return "SETECIENTOS";
				case 900: return "NOVECIENTOS";
				case 1000: return "MIL";
				case 1000000: return "UN MILLON";
				case 1000000000000: return "UN BILLON";

				default:
					if (pintValor < 20) { return "DIECI" + ConvertNumberToWordsESCO(pintValor - 10); }

					else if (pintValor < 30) { return "VEINTI" + ConvertNumberToWordsESCO(pintValor - 20); }

					else if (pintValor < 100) { return ConvertNumberToWordsESCO((ulong)(pintValor / 10) * 10) + " Y " + ConvertNumberToWordsESCO(pintValor % 10); }

					else if (pintValor < 200) { return "CIENTO " + ConvertNumberToWordsESCO(pintValor - 100); }

					else if (pintValor == 200 || pintValor == 300 || pintValor == 400 || pintValor == 600 || pintValor == 800) { return ConvertNumberToWordsESCO((ulong)(pintValor / 100)) + "CIENTOS"; }

					else if (pintValor < 1000) { return ConvertNumberToWordsESCO((ulong)(pintValor / 100) * 100) + " " + ConvertNumberToWordsESCO(pintValor % 100); }

					else if (pintValor < 2000) { return "MIL " + ConvertNumberToWordsESCO(pintValor % 1000); }

					else if (pintValor < 1000000)
					{
						strTemp = ConvertNumberToWordsESCO((ulong)(pintValor / 1000)) + " MIL";
						if (pintValor % 1000 > 0) { return strTemp + " " + ConvertNumberToWordsESCO(pintValor % 1000); }
					}

					else if (pintValor < 2000000) { return "UN MILLON " + ConvertNumberToWordsESCO(pintValor % 1000000); }

					else if (pintValor < 1000000000000)
					{
						strTemp = ConvertNumberToWordsESCO((ulong)(pintValor / 1000000)) + " MILLONES ";
						if ((pintValor - (ulong)(pintValor / 1000000) * 1000000) > 0) { return strTemp + " " + ConvertNumberToWordsESCO(pintValor - (ulong)(pintValor / 1000000) * 1000000); }
						return strTemp;
					}

					else if (pintValor < 2000000000000) 
					{
						return "UN BILLON " + ConvertNumberToWordsESCO(pintValor - (ulong)(pintValor / 1000000000000) * 1000000000000); 
					}
					
					else
					{
						strTemp = ConvertNumberToWordsESCO((ulong)(pintValor / 1000000000000)) + " BILLONES";

						if ((pintValor - ((ulong)(pintValor / 1000000000000) * 1000000000000)) > 0)
						{
							return strTemp + " " + ConvertNumberToWordsESCO(pintValor - (ulong)(pintValor / 1000000000000) * 1000000000000);
						}
					}

					return strTemp;
			}
		}
		
		
		public static string RellenarCerosIzquierda (int pValor, int pLongitud)
		{
			string resultado;
			int diferencia;
			
			
			resultado = pValor.ToString ();
			
			diferencia = pLongitud - resultado.Length;
			
			if (diferencia == 0) { return resultado; }
			else if (diferencia < 0)
			{
				throw new GenericException (string.Format ("La longitud {0} es interior a la de la cadena a convertir {1}: {2}", pLongitud, pValor, resultado.Length));
			}
			
			return new String ('0', diferencia) + resultado;
		}
		
		#endregion
		
		
		#region Funciones
	
		public static float GetFloatFromMultiplePoints (string pValue)
		{
			return GetFloatFromMultiplePoints (pValue, 0);
		}
		
		
		public static float GetFloatFromMultiplePoints (string pValue, float pDefaultValue)
		{
			string [] parts;
			
			
			if (string.IsNullOrEmpty (pValue))
			{
				return pDefaultValue;
			}
			
			parts = pValue.Split ('.');
			
			if (parts.Length == 1)
			{
				pValue = parts [0];
			}
			else if (parts.Length > 1)
			{
				pValue = parts [0] + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + parts [1];
			}
			
			return GetFloat (pValue, pDefaultValue);
		}
		
		
		public static double GetDoubleFromMultiplePoints (string pValue)
		{
			return GetDoubleFromMultiplePoints (pValue, 0);
		}
		
		
		public static double GetDoubleFromMultiplePoints (string pValue, double pDefaultValue)
		{
			string [] parts;
			
			
			if (string.IsNullOrEmpty (pValue))
			{
				return pDefaultValue;
			}
			
			parts = pValue.Split ('.');
			
			if (parts.Length == 1)
			{
				pValue = parts [0];
			}
			else if (parts.Length > 1)
			{
				pValue = parts [0] + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + parts [1];
			}
			
			return GetDouble (pValue, pDefaultValue);
		}
		
		
		public static bool IsEmpty (string pstrCadena)
		{
			if (string.IsNullOrEmpty (pstrCadena)) { return true; }
			
			pstrCadena = pstrCadena.Trim ();
			
			if (string.IsNullOrEmpty (pstrCadena)) { return true; }
			
			return false;
		}
		
		
		public static string ConcatenateKeyValue (string pstrRightSeparator, params string [] pKeyValue)
		{	
			StringBuilder result;


			if (DataHelper.IsEmpty (pKeyValue)) { return null; }

			result = new StringBuilder ();

			for (int i = 0; i < pKeyValue.Length; i+=2)
			{
				if (!IsEmpty (pKeyValue [i + 1]))
				{
					result.AppendFormat ("{0}{1}{2}", pKeyValue [i], pKeyValue [i + 1], pstrRightSeparator);
				}
			}

			if (result.Length > 0)
			{
				result.Length -= pstrRightSeparator.Length;
			}

			return result.ToString ();
		}


		public static string ConcatenateKeyValue (string pstrRightSeparator, params object [] pKeyValue)
		{	
			StringBuilder result;


			if (DataHelper.IsEmpty (pKeyValue)) { return null; }

			result = new StringBuilder ();

			for (int i = 0; i < pKeyValue.Length; i+=2)
			{
				if (pKeyValue [i + 1] != null && !IsEmpty (pKeyValue [i + 1].ToString ()))
				{
					result.AppendFormat ("{0}{1}{2}", pKeyValue [i], pKeyValue [i + 1], pstrRightSeparator);
				}
			}

			if (result.Length > 0)
			{
				result.Length -= pstrRightSeparator.Length;
			}

			return result.ToString ();
		}
		
		
		public static string Concatenate (string pRightSeparator, string pstrKey, List<Dictionary<string, string>> pDiccionarios)
		{
			StringBuilder stbResult;
			
			
			if (string.IsNullOrEmpty (pRightSeparator) || pDiccionarios == null || pDiccionarios.Count == 0) { return string.Empty; }
			
			stbResult = new StringBuilder ();
			
			foreach (Dictionary<string, string> diccionario in pDiccionarios)
			{
				if (!string.IsNullOrEmpty (diccionario [pstrKey]))
				{
					stbResult.Append (diccionario [pstrKey]);
					stbResult.Append (pRightSeparator);
				}
			}
			
			if (stbResult.Length > 0)
			{
				stbResult.Length -= pRightSeparator.Length;
			}
			
			return stbResult.ToString ();
		}


		public static string Concatenate<T> (string pRightSeparator, List<T> pItems)
		{
			StringBuilder stbResult;


			if (string.IsNullOrEmpty(pRightSeparator) || DataHelper.IsEmpty (pItems)) { return string.Empty; }

			stbResult = new StringBuilder();

			foreach (T item in pItems)
			{
				stbResult.Append(item.ToString ());
				stbResult.Append(pRightSeparator);
			}

			if (stbResult.Length > 0)
			{
				stbResult.Length -= pRightSeparator.Length;
			}

			return stbResult.ToString();
		} 


		public static string Concatenate(string pRightSeparator, NameValueCollection pListKeyValue)
		{
			StringBuilder stbResult;


			if (string.IsNullOrEmpty(pRightSeparator) || DataHelper.IsEmpty (pListKeyValue)) { return string.Empty; }

			stbResult = new StringBuilder();

			foreach (string key in pListKeyValue.AllKeys)
			{
				stbResult.AppendFormat("{0}: {1}", key, pListKeyValue[key]);
				stbResult.Append(pRightSeparator);
			}

			if (stbResult.Length > 0)
			{
				stbResult.Length -= pRightSeparator.Length;
			}

			return stbResult.ToString();
		}
		
		
		public static string DefaultTextIfEmpty (string pValue, string pDefaultValue)
		{
			if (IsEmpty (pValue))
			{
				return pDefaultValue;
			}
			
			return pValue;
		}


		public static string FormatName (string pFormat, IList<BasicReference> pReferences)
		{
			StringBuilder stbResult;
			
		
			if (DataHelper.IsEmpty (pReferences)) { return string.Empty; }
			
			stbResult = new StringBuilder ();
			
			foreach (BasicReference item in pReferences)
			{
				if (item != null && !IsEmpty (item.Name))
				{
					stbResult.AppendFormat (pFormat, item.Name);
				}
			}

			return stbResult.ToString ();
		}


		public static string Format (string pFormat, params string [] pValues)
		{
			StringBuilder stbResult;


			if (DataHelper.IsEmpty(pValues)) { return string.Empty; }

			stbResult = new StringBuilder();

			foreach (string item in pValues)
			{
				if (!IsEmpty(item))
				{
					stbResult.AppendFormat(pFormat, item);
				}
			}

			return stbResult.ToString();
		}
		
		
		public static string Concatenate (string pstrRightSeparator, params string [] pstrValues)
		{
			StringBuilder stbResult;
			
		
			if (DataHelper.IsEmpty (pstrValues)) { return string.Empty; }
			
			stbResult = new StringBuilder ();
			
			foreach (string strValue in pstrValues)
			{
				if (!string.IsNullOrEmpty (strValue))
				{
					stbResult.Append (strValue);
					stbResult.Append (pstrRightSeparator);
				}
			}
			
			if (stbResult.Length > 0)
			{
				stbResult.Length --;
			}
			
			return stbResult.ToString ();
		}
		
		
		public static string Capitalize (string pCadena)
        {
			if (string.IsNullOrEmpty(pCadena)) { return pCadena; }
            
            return pCadena.Substring(0, 1).ToUpper() + pCadena.Substring(1).ToLower();
        }
        
        
        public static string GenerateNameValueString (string pTitle, params object [] pKeyValues)
		{
			StringBuilder stbResultado;
			
			int intI;
			
			
			stbResultado = new StringBuilder (pTitle + ":");
			
			if (pKeyValues.Length == 0) { stbResultado.Append (" NOT DEFINED "); }
			
			if (pKeyValues.Length == 1) { stbResultado.Append (pKeyValues [0]); }
			
			else
			{
				for (intI = 0; intI < pKeyValues.Length; intI += 2)
				{
					stbResultado.AppendFormat ("\t\n{0}: ", pKeyValues [intI]);
					
					if (pKeyValues [intI + 1] != null)
					{
						stbResultado.Append (pKeyValues [intI + 1].ToString ());
					}
				}
			}
			
			return stbResultado.ToString ();
		}
		
		
		public static string GenerateDescriptiveString (object [] pobjObjects)
		{
			StringBuilder stbResultado;
			
			
			stbResultado = new StringBuilder ();
			
			if (pobjObjects == null || pobjObjects.Length == 0) { stbResultado.Append ("\t\nEMPTY"); }
			else
			{
				foreach (object objObjeto in pobjObjects)
				{
					if (objObjeto == null) { stbResultado.Append ("\t\nNULL"); }
					else { stbResultado.Append (objObjeto.ToString ()); }
				}
			}
			
			return stbResultado.ToString ();
		}
		
		#endregion


		#region Funciones para SQL
		
		public static string FormatLIKE (string pValor, ComparisonTypes penuComparisonType)
		{
			if (IsEmpty (pValor)) { return null; }
			else 
			{
				switch (penuComparisonType)
				{
					case ComparisonTypes.LikeFull:
						return "%" + pValor.Replace ("%", string.Empty) + "%";
						
					case ComparisonTypes.LikeLeft: 
						return "%" + pValor.Replace ("%", string.Empty); 
					
					case ComparisonTypes.LikeRight:
						return pValor.Replace ("%", string.Empty) + "%";
				}
			}
			
			return pValor;
		}
		
		
		public static string GenerateINIDs (bool pAddINText, params byte [] pbytValues)
		{
			object [] pobjValues;


			pobjValues = new object [pbytValues.Length];

			Array.Copy (pbytValues, pobjValues, pbytValues.Length);

			return GenerateIN (false, pAddINText, pobjValues);
		}


		public static string GenerateINIDs (bool pAddINText, params long [] pshrValues)
		{
			object [] pobjValues;


			pobjValues = new object [pshrValues.Length];

			Array.Copy (pshrValues, pobjValues, pshrValues.Length);

			return GenerateIN (false, pAddINText, pobjValues);
		}
		

		public static string GenerateINIDs (bool pAddINText, params int [] pintValues)
		{
			object [] pobjValues;
			
			
			pobjValues = new object [pintValues.Length];
			
			Array.Copy (pintValues, pobjValues, pintValues.Length);

			return GenerateIN (false, pAddINText, pobjValues);
		}


		public static string GenerateINIDs (bool pAddINText, params int? [] pintValues)
		{
			object [] pobjValues;
			
			
			pobjValues = new object [pintValues.Length];
			
			Array.Copy (pintValues, pobjValues, pintValues.Length);

			return GenerateIN (false, pAddINText, pobjValues);
		}
		
		
		public static string GenerateINIDs (bool pAddINText, params ushort [] pintValues)
		{
			object [] pobjValues;
			
			
			pobjValues = new object [pintValues.Length];
			
			Array.Copy (pintValues, pobjValues, pintValues.Length);

			return GenerateIN (false, pAddINText, pobjValues);
		}
		

		public static string GenerateIN (bool pAddINText, params string [] pstrValues)
		{
			return GenerateIN (true, pAddINText, pstrValues);
		}


		public static string GenerateIN (bool pblnEsCadena, bool pAddINText, object [] pobjValues)
		{
			int intI;
			
			StringBuilder stbResultado;
			
			
			if (DataHelper.IsEmpty (pobjValues)) { return string.Empty; }
			
			stbResultado = new StringBuilder ();
		
			if (pAddINText)
			{
				stbResultado.Append (" IN (");
			}

			if (pblnEsCadena)
			{
				stbResultado.Append ("'" + pobjValues [0] + "'");
			}
			else
			{
				stbResultado.Append (pobjValues [0]);
			}
		
			for (intI = 1; intI < pobjValues.Length; intI ++)
			{
				if (pblnEsCadena)
				{
					stbResultado.AppendFormat (",'{0}'", pobjValues [intI].ToString ().Replace ("'", "\'"));
				}
				else
				{
					stbResultado.AppendFormat (",{0}", pobjValues [intI].ToString ());
				}
			}

			if (pAddINText)
			{
				stbResultado.Append (") ");
			}
			
			return stbResultado.ToString ();
		}
		
		#endregion

		
		#region Hash
		
		public static string GetMD5Hash(string pData)
		{
			return GetMD5Hash (System.Text.Encoding.Default.GetBytes (pData));
		}

		public static string GetMD5Hash (byte[] pData)
		{
			using (MD5 md5 = MD5.Create ())
			{
				return BitConverter.ToString (md5.ComputeHash (pData));
			}
		}

		// TODO: Verificar que pasa con archivos grandes (2Gb por ejemplo)
		public static string GetMD5HashFile (string pFileName)
		{
			FileHelper.WaitFileLocked (pFileName);

			byte[] hash = MD5.Create().ComputeHash (File.ReadAllBytes(pFileName));
			
			return BitConverter.ToString (hash).Replace ("-", "");
		}

		#endregion
		

		#region Encripcion
		
		private static string RSAKey = "UJYHCX783her*&5@$%#(MJCX**38n*#6835ncv56tvbry(&#MX98cn342cn4*&X#&";
		
		
		public static string EncryptSHA1(string pValue)   
		{   
			SHA1 hash;
			
			ASCIIEncoding encoder;
			
			
			hash = SHA1.Create();   
			encoder = new ASCIIEncoding();
			
			hash.ComputeHash(encoder.GetBytes(pValue));
			
			return Convert.ToBase64String(hash.Hash); 
		} 
		
		
		public static string EncryptRSA (string pValue)
		{
			if (IsEmpty (pValue)) { return null; }
		
			// We are now going to create an instance of the
			// Rihndael class.
			RijndaelManaged RijndaelCipher = new RijndaelManaged();
			// First we need to turn the input strings into a byte array.
			byte[] PlainText = System.Text.Encoding.Unicode.GetBytes(pValue);
			// We are using Salt to make it harder to guess our key
			// using a dictionary attack.
			byte[] Salt = Encoding.ASCII.GetBytes(RSAKey.Length.ToString());
			// The (Secret Key) will be generated from the specified
			// password and Salt.
			//PasswordDeriveBytes -- It Derives a key from a password
			PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(RSAKey, Salt);
			// Create a encryptor from the existing SecretKey bytes.
			// We use 32 bytes for the secret key
			// (the default Rijndael key length is 256 bit = 32 bytes) and
			// then 16 bytes for the IV (initialization vector),
			// (the default Rijndael IV length is 128 bit = 16 bytes)
			ICryptoTransform Encryptor = RijndaelCipher.CreateEncryptor(SecretKey.GetBytes(16), SecretKey.GetBytes(16));
			// Create a MemoryStream that is going to hold the encrypted bytes
			MemoryStream memoryStream = new MemoryStream();
			// Create a CryptoStream through which we are going to be processing our data.
			// CryptoStreamMode.Write means that we are going to be writing data
			// to the stream and the output will be written in the MemoryStream
			// we have provided. (always use write mode for encryption)
			CryptoStream cryptoStream = new CryptoStream(memoryStream, Encryptor, CryptoStreamMode.Write);
			// Start the encryption process.
			cryptoStream.Write(PlainText, 0, PlainText.Length);
			// Finish encrypting.
			cryptoStream.FlushFinalBlock();
			// Convert our encrypted data from a memoryStream into a byte array.
			byte[] CipherBytes = memoryStream.ToArray();
			// Close both streams.
			memoryStream.Close();
			cryptoStream.Close();
			// Convert encrypted data into a base64-encoded string.
			// A common mistake would be to use an Encoding class for that.
			// It does not work, because not all byte values can be
			// represented by characters. We are going to be using Base64 encoding
			// That is designed exactly for what we are trying to do.
			return Convert.ToBase64String(CipherBytes);
		}
		
		
		public static string DecryptRSA (string pValue, string pErrorDefaultValue)
		{
			try
			{
				if (string.IsNullOrEmpty (pValue))
				{
					return pErrorDefaultValue;
				}
			
				return DecryptRSA (pValue);
			}
			catch (Exception pEx)
			{
				Log.Error (pEx);
				
				return pErrorDefaultValue;
			}
		}
		
		
		public static string DecryptRSA (string pValue)
		{
			RijndaelManaged RijndaelCipher = new RijndaelManaged();
			byte[] EncryptedData = Convert.FromBase64String(pValue);
			byte[] Salt = Encoding.ASCII.GetBytes(RSAKey.Length.ToString());
			PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(RSAKey, Salt);
			// Create a decryptor from the existing SecretKey bytes.
			ICryptoTransform Decryptor = RijndaelCipher.CreateDecryptor(SecretKey.GetBytes(16), SecretKey.GetBytes(16));
			MemoryStream memoryStream = new MemoryStream(EncryptedData);
			// Create a CryptoStream. (always use Read mode for decryption).
			CryptoStream cryptoStream = new CryptoStream(memoryStream, Decryptor, CryptoStreamMode.Read);
			// Since at this point we don't know what the size of decrypted data
			// will be, allocate the buffer long enough to hold EncryptedData;
			// DecryptedData is never longer than EncryptedData.
			byte[] PlainText = new byte[EncryptedData.Length];
			// Start decrypting.
			int DecryptedCount = cryptoStream.Read(PlainText, 0, PlainText.Length);
			memoryStream.Close();
			cryptoStream.Close();
			// Convert decrypted data into a string.
			return Encoding.Unicode.GetString(PlainText, 0, DecryptedCount);
		}
		
		
		public static string Compress(string pText)
		{
			byte[] buffer = Encoding.UTF8.GetBytes(pText);
			
			MemoryStream ms = new MemoryStream();
			
			
			using (GZipStream zip = new GZipStream (ms, CompressionMode.Compress, true))
			{
				zip.Write(buffer, 0, buffer.Length);
			}

			ms.Position = 0;
			
			MemoryStream outStream = new MemoryStream();

			byte[] compressed = new byte[ms.Length];
			ms.Read(compressed, 0, compressed.Length);

			byte[] gzBuffer = new byte[compressed.Length + 4];
			
			Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
			Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
			
			return Convert.ToBase64String (gzBuffer);
		}


		public static string DeCompress(string pZippedText)
		{
			byte[] gzBuffer = Convert.FromBase64String(pZippedText);
			
			
			using (MemoryStream ms = new MemoryStream())
			{
				int msgLength = BitConverter.ToInt32(gzBuffer, 0);
				
				int length = gzBuffer.Length;
				
				length -= 4;
				
				ms.Write(gzBuffer, 4, length);

				byte[] buffer = new byte[msgLength];

				ms.Position = 0;
				
				using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
				{
					zip.Read(buffer, 0, buffer.Length);
				}

				return Encoding.UTF8.GetString(buffer);
			}	 
		}
		
		#endregion
		
		
		#region Funciones de Conversion Basica
		
		public static string GetDateText (DateTime? pValue)
		{
			return GetDateText (pValue, DEFAULT_DATE_FORMAT);
		}
		
		public static string GetDateText (DateTime? pValue, string pFormat)
		{
			if (pValue == null) { return string.Empty; }

			return pValue.Value.ToString (pFormat);
		}


		public static DateTime? GetNullableDate (string pValue)
		{
			return GetNullableDate (pValue, DEFAULT_DATE_FORMAT);
		}


		public static DateTime? GetNullableDate(string pValue, params string [] pFormats)
		{
			DateTime value;
			
		
			if (IsEmpty (pValue))
			{
				return null;
			}

			if (DataHelper.IsEmpty (pFormats))
			{
				pFormats = new string [] { DEFAULT_DATE_FORMAT };
			}

			foreach (string format in pFormats)
			{
				if (DateTime.TryParseExact (pValue, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out value))
				{
					return value;
				}
			}
			
			return null;
		}


		public static DateTime GetDate(string pValue, params string [] pFormats)
		{
			DateTime? value;
			
		
			value = GetNullableDate (pValue, pFormats);
			
			if (value == null)
			{
				return DateTime.MinValue;
			}

			return value.Value;
		}


		public static DateTime GetDateTime (string pValue, params string [] pFormats)
		{
			DateTime? value;


			value = GetNullableDateTime(pValue, pFormats);

			if (value == null)
			{
				return DateTime.MinValue;
			}

			return value.Value;
		}


		public static DateTime? GetNullableDateTime (string pValue, params string [] pFormats)
		{
			DateTime value;
			
		
			if (IsEmpty (pValue))
			{
				return null;
			}

			if (DataHelper.IsEmpty(pFormats))
			{
				pFormats = new string[] { DEFAULT_DATETIME_FORMAT };
			}
			
			
			foreach (string format in pFormats)
			{
				if (DateTime.TryParseExact (pValue, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out value))
				{
					return value;
				}
			}
			
			if (DateTime.TryParse (pValue, out value))
			{
				return value;
			}

			return null;
		}


		public static string ClearForNumber (string pValue)
		{
			return pValue.Replace ("$", string.Empty).Replace ("%", string.Empty).Replace (Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencySymbol, string.Empty).Trim ();
			//return Regex.Replace (pValue, @"\$\%\" + Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencySymbol, string.Empty).Trim ();
		}


		public static int GetInt (string pValue)
		{
			return GetInt (pValue, 0);
		}
		
		
		public static int GetInt (string pValue, int pDefaultValue)
		{
			int value;
			
			
			if (!int.TryParse (ClearForNumber (pValue), out value))
			{
				return pDefaultValue;
			}
			
			return value;
		}
		
		
		public static int? GetNullableInt (string pValue)
		{
			int value;
			
			
			if (IsEmpty (pValue) || !int.TryParse (ClearForNumber (pValue), out value))
			{
				return null;
			}
			
			return value;
		}
		
		
		public static long GetLong (string pValue)
		{
			long value;
			
			
			long.TryParse (ClearForNumber (pValue), out value);
			
			return value;
		}


		public static long? GetNullableLong (string pValue)
		{
			long value;
			
			
			if (IsEmpty (pValue) || !long.TryParse (ClearForNumber (pValue), out value))
			{
				return null;
			}
			
			return value;
		}
		
		
		public static float GetFloat (string pValue)
		{
			return GetFloat (pValue, 0);
		}
		
		
		public static float GetFloat (string pValue, float pDefaultValue)
		{
			float value;
			
			
			if (!float.TryParse (ClearForNumber (pValue), out value))
			{
				return pDefaultValue;
			}
			
			return value;
		}


		public static float? GetNullableFloat (string pValue)
		{
			float value;
			
			
			if (IsEmpty (pValue) || !float.TryParse (ClearForNumber (pValue), out value))
			{
				return null;
			}
			
			return value;
		}
		
		
		public static double GetDouble (string pValue)
		{
			return GetDouble (pValue, 0);
		}
		
		
		public static double GetDouble (string pValue, double pDefaultValue)
		{
			double value;
			
			
			if (!double.TryParse (ClearForNumber (pValue), out value))
			{
				return pDefaultValue;
			}
			
			return value;
		}		


		public static double? GetNullableDouble (string pValue)
		{
			double value;
			
			
			if (IsEmpty (pValue) || !double.TryParse (ClearForNumber (pValue), out value))
			{
				return null;
			}
			
			return value;
		}


		public static byte GetByte (string pValue)
		{
			return GetByte (pValue, 0);
		}
		
		
		public static byte GetByte (string pValue, byte pDefaultValue)
		{
			byte value;
			
			
			if (!byte.TryParse (ClearForNumber (pValue), out value))
			{
				return pDefaultValue;
			}
			
			return value;
		}		


		public static byte? GetNullableByte (string pValue)
		{
			byte value;
			
			
			if (IsEmpty (pValue) || !byte.TryParse (ClearForNumber (pValue), out value))
			{
				return null;
			}
			
			return value;
		}
		
		
		public static bool GetBool (string pValue, bool pDefaultValue)
		{
			if (IsEmpty (pValue)) { return pDefaultValue; }

			pValue = pValue.Trim ().ToUpper ();

			if (pValue == "SI" || pValue == "TRUE" || pValue == "1" || pValue == "VERDADERO" || pValue == "CIERTO" || pValue == "OK" || pValue == "CORRECTO")
			{
				return true;
			}

			return pDefaultValue;
		}
		
		
		public static bool GetBool (string pValue)
		{
			return GetBool (pValue, false);
		}
		
		
		public static bool? GetNullableBool (string pValue)
		{
			if (IsEmpty (pValue))
			{
				return null;
			}
			
			return GetBool (pValue);
		}
		
		#endregion


		#region Funciones de Extraccion
		
		public static string ExtractString (string pFieldName, string pValue, int maxLength)
		{
			return ExtractString (pFieldName, pValue, maxLength, null, string.Empty);
		}
		
		
		public static string ExtractString (string pFieldName, string pValue, int maxLength, string pDefaultValueIfEmpty, string pEndDeco)
		{
			if (IsEmpty (pValue))
			{
				return pDefaultValueIfEmpty;
			}
			
			pValue = pValue.Trim ();
			
			if (pValue.Length <= maxLength)
			{
				return pValue;
			}
			
			return pValue.Substring (0, maxLength - 1) + pEndDeco;
		}
		
		
		public static string ExtractStringInt (string pFieldName, string pValue, int maxLength)
		{
			return ExtractStringInt (pFieldName, pValue, maxLength, null);
		}
		
		
		public static string ExtractStringInt (string pFieldName, string pValue, int maxLength, int? pDefaultValueIfEmpty)
		{
			int temp;
			
		
			if (IsEmpty (pValue))
			{
				if (pDefaultValueIfEmpty == null)
				{
					return null;
				}
				
				return pDefaultValueIfEmpty.Value.ToString ();
			}
			
			pValue = pValue.Trim ();
			
			if (!int.TryParse (ClearForNumber (pValue), out temp))
			{
				throw new GenericException (string.Format ("El formato para el valor {0} no corresponde aun valor entero", pValue));
			}
			
			if (pValue.Length <= maxLength)
			{
				return pValue;
			}
			
			return pValue.Substring (0, maxLength - 1);
		}
		
		
		public static string ExtractStringLong (string pFieldName, string pValue, int maxLength)
		{
			return ExtractStringLong (pFieldName, pValue, maxLength, null);
		}
		
		
		public static string ExtractStringLong (string pFieldName, string pValue, int maxLength, int? pDefaultValueIfEmpty)
		{
			long temp;
			
		
			if (IsEmpty (pValue))
			{
				if (pDefaultValueIfEmpty == null)
				{
					return null;
				}
				
				return pDefaultValueIfEmpty.Value.ToString ();
			}
			
			pValue = pValue.Trim ();
			
			if (!long.TryParse (ClearForNumber (pValue), out temp))
			{
				throw new GenericException (string.Format ("El formato para el valor {0} no corresponde aun valor entero grande", pValue));
			}
			
			if (pValue.Length <= maxLength)
			{
				return pValue;
			}
			
			return pValue.Substring (0, maxLength - 1);
		}
		
		
		public static string ExtractStringDate (string pFieldName, DateTime pDateTime, int pMaxLength, string pFormat)
		{
			return ExtractStringDate (pFieldName, pDateTime, pMaxLength, pFormat, null);
		}
		
		
		public static string ExtractStringDate (string pFieldName, DateTime pDateTime, int pMaxLength, string pFormat, string pDefaultValueIfMinValue)
		{
			if (pDateTime == DateTime.MinValue)
			{
				return pDefaultValueIfMinValue;
			}
			
			return string.Format("{0:" + pFormat + "}", pDateTime);
		}
		
		
		public static string ExtractStringDate (string pFieldName, string pPreFormatedDateTime, int pMaxLength, string pFormat)
		{
			return ExtractStringDate (pFieldName, pPreFormatedDateTime, pMaxLength, pFormat, null);
		}
		
		
		public static string ExtractStringDate (string pFieldName, string pPreFormatedDateTime, int pMaxLength, string pFormat, string pDefaultValueIfMinValue)
		{
			DateTime dtmDate;
			
			
			if (!DateTime.TryParseExact (pPreFormatedDateTime, pFormat, System.Globalization.CultureInfo.CurrentCulture, System.Globalization.DateTimeStyles.None, out dtmDate))
			{
				throw new GenericException (string.Format ("El formato {0} para el valor {1} no corresponde a una fecha", pFormat, pPreFormatedDateTime));
			}
			
			return ExtractStringDate (pFieldName, dtmDate, pMaxLength, pFormat, pDefaultValueIfMinValue);
		}
		
		#endregion
		
		
		#region Funciones Stopwatch
		
		public static string ToString (ref Stopwatch pStopwatch)
		{
			string result;
			
			
			if (pStopwatch.IsRunning)
			{
				pStopwatch.Stop ();
				result = ToStringMS (pStopwatch.ElapsedMilliseconds);
				pStopwatch.Start ();
			}
			else
			{
				result = ToStringMS (pStopwatch.ElapsedMilliseconds);
			}
			
			return result;
		}
		
		
		public static string ToStringMS (long pMilliseconds)
		{
			string result;
		
			
			// Milisegundos
			if (pMilliseconds <= 1000)
			{
				result = string.Format ("{0:0.##}ms", pMilliseconds);
			}
			// Segundos
			else if (pMilliseconds <= 60000)
			{
				result = string.Format ("{0:0.##}s", ((double) pMilliseconds / 1000));
			}
			// Minutos
			else if (pMilliseconds <= 3600000)
			{
				result = string.Format ("{0:0.##}m", ((double) pMilliseconds / 60000));
			}
			else
			{
				// Horas			
				result = string.Format ("{0:0.##}h", ((double) pMilliseconds / (60000 * 24)));
			}
			
			return result;
		}
		
		
		public static string ToStringBytes (byte [] pBytes)
		{
			if (pBytes == null) { return "NULL"; }

			return ToStringBytes (pBytes.LongLength);
		}


		public static string ToStringBytes (long? pLenghtBytes)
		{
			if (pLenghtBytes == null) { return string.Empty; }
			
			const int scale = 1024;
			
			string[] orders = new string[] { "GB", "MB", "KB", "Bytes" };
			
			long max = (long)Math.Pow(scale, orders.Length - 1);

			foreach (string order in orders)
			{
				if (pLenghtBytes > max)
				{
					return string.Format("{0:##.##} {1}", decimal.Divide(pLenghtBytes.Value, max), order);
				}
				
				max /= scale;
			}
			
			return "0 Bytes";
		}


		public static string ToString (DateTime pDateTime, string pFormat = null)
		{
			if (string.IsNullOrWhiteSpace(pFormat))
			{
				pFormat = DEFAULT_DATETIME_LONGFORMAT;
			}

			return pDateTime.ToString(pFormat);
		}


		public static string ToString (DateTime? pDateTime, string pFormat = null)
		{
			if (pDateTime == null)
			{
				return string.Empty;
			}

			return ToString (pDateTime.Value, pFormat);
		}


		public static string ToString (int? pValue)
		{
			if (pValue == null)
			{	
				return string.Empty;
			}

			return pValue.Value.ToString ();
		}


		public static string ToString(long? pValue)
		{
			if (pValue == null)
			{
				return string.Empty;
			}

			return pValue.Value.ToString();
		}


		public static string ToString(byte? pValue)
		{
			if (pValue == null)
			{
				return string.Empty;
			}

			return pValue.Value.ToString();
		}


		public static string ToString(short? pValue)
		{
			if (pValue == null)
			{
				return string.Empty;
			}

			return pValue.Value.ToString();
		}


		public static string ToString<O> (O pValue, string pFormat = null) where O : class
		{
			if (pValue == null)
			{
				return string.Empty;
			}

			return pValue.ToString ();
		}
		
		#endregion
		
		
		#region Funciones de Texto en Lista
		
		public static string GenerateList (NameValueCollection pList)
		{
			return GenerateList ('|', pList);
		}
		
		
		public static string GenerateList (char pSeparator, NameValueCollection pList)
		{
			StringBuilder stbResult;
			
			
			stbResult = new StringBuilder ();
			
			foreach (string key in pList.AllKeys)
			{
				stbResult.AppendFormat (string.Format ("{0}{1}{2}{1}", key, pSeparator, pList [key]));
			}
			
			stbResult.Length --;
			
			return stbResult.ToString ();
		}
		
		
		public static string GenerateList (char pSeparator, params string [] pNameValue)
		{
			StringBuilder stbResult;
			
			
			stbResult = new StringBuilder ();
			
			if (pNameValue.Length % 2 != 0)
			{
				throw new Exception (string.Format ("The list of Name/Values must be even but has {0} elements", pNameValue.Length));
			}
			
			for (int i = 0; i < pNameValue.Length; i += 2)
			{
				stbResult.AppendFormat (string.Format ("{0}{1}{2}{1}", pNameValue [i], pSeparator, pNameValue [i + 1]));
			}
			
			stbResult.Length --;
			
			return stbResult.ToString ();
		}
		
		
		public static NameValueCollection FromStringList (string pList)
		{
			return FromStringList ('|', pList);
		}
		
		
		public static NameValueCollection FromStringList (char pSeparator, string pList)
		{
			string [] parts;
			
			NameValueCollection list;
			
			
			parts = pList.Split (pSeparator);
			
			if (parts.Length % 2 != 0)
			{
				throw new Exception (string.Format ("The list of Name/Values must be even but has {0} elements", parts.Length));
			}
			
			list = new NameValueCollection (parts.Length / 2);
			
			for (int i = 0; i < parts.Length; i += 2)
			{
				list.Add (parts [i], parts [i + 1]);
			}
			
			return list;
		}
		
		#endregion
		
		
		#region Listados
		
		public static List<BasicReference> GetRangeList (int pStart, int pEnd)
		{
			List<BasicReference> lstRange;
			
			
			lstRange = new List<BasicReference> ();
			
			do
			{
				lstRange.Add (new BasicReference () { ID = pStart, Code = pStart.ToString (), Name = pStart.ToString () });
				
				pStart ++;
				
			} while (pStart <= pEnd);
			
			return lstRange;
		}
		
		#endregion
		
		
		#region Nombres
		
		public static string ConcatPartsAvoidEmptyParts<O> (string pConcatenatorLeft, string pConcatenatorRight, List<O> pParts)
		{
			List<string> parts;


			if (DataHelper.IsEmpty (pParts)) { return string.Empty; }

			parts = new List<string> (pParts.Count);

			foreach (O item in pParts)
			{
				parts.Add (item.ToString()); 
			}

			return ConcatPartsAvoidEmptyParts (pConcatenatorLeft, pConcatenatorRight, parts.ToArray ());
		}
		
		
		public static string ConcatPartsAvoidEmptyParts (string pConcatenatorLeft, string pConcatenatorRight, params string [] pParts)
		{
			StringBuilder stbResult;
			
		
			if (pParts == null || pParts.Length == 0)
			{
				return string.Empty;
			}
			
			stbResult = new StringBuilder ();
			
			foreach (string part in pParts)
			{
				if (!string.IsNullOrEmpty (part))
				{
					stbResult.Append (string.Format ("{0}{1}{2}", pConcatenatorLeft, part.Trim (), pConcatenatorRight)); 
				}
			}

			return stbResult.ToString ().Trim ();
		}
		
		#endregion
		
		
		#region Validacion de Expresiones Regulares
		
		public static bool IsMatch (string pRegularExpression, params string [] pLines)
		{
			if (pLines == null || pLines.Length == 0) { return true; }
		
			foreach (string line in pLines)
			{
				if (!Regex.IsMatch (line.Trim (), pRegularExpression))
				{
					return false;
				}
			}
			
			return true;
		}
		
		#endregion
		

		#region Reemplazo

		public static string [] Replace (string pReplaceThis, string pReplaceWith, params string [] pValues)
		{
			if (DataHelper.IsEmpty (pValues)) { return null; }

			for (int i = 0; i < pValues.Length; i++)
			{
				pValues [i] = pValues [i].Replace (pReplaceThis, pReplaceWith);
			}

			return pValues;
		}


		public static List<string> Replace (string pReplaceThis, string pReplaceWith, List<string> pValues)
		{
			if (DataHelper.IsEmpty (pValues)) { return null; }

			for (int i = 0; i < pValues.Count; i++)
			{
				pValues [i] = pValues [i].Replace (pReplaceThis, pReplaceWith);
			}

			return pValues;
		}


		public static string ReplaceAllRemoveLFLN (string pValue, string pReplaceWith, params string [] pReplaceThese)
		{
			List<string> replaces;


			if (DataHelper.IsEmpty (pReplaceThese))
			{
				replaces = new List<string> ();
			}
			else
			{
				replaces = new List<string> (pReplaceThese);
			}

			replaces.Add (Environment.NewLine);
			replaces.Add ("\r");

			return ReplaceAll (pValue, pReplaceWith, replaces.ToArray ());
		}


		public static string ReplaceAll (string pValue, string pReplaceWith, params string [] pReplaceThese)
		{
			if (DataHelper.IsEmpty (pReplaceThese))
			{
				return pValue;
			}

			foreach (string toReplace in pReplaceThese)
			{
				if (!IsEmpty (toReplace))
				{
					pValue = pValue.Replace (toReplace, pReplaceWith);
				}
			}

			return pValue;
		}


		public static string RemoveDiacritics (string pText)
		{
			return string.Concat(
				pText.Normalize(NormalizationForm.FormD)
				.Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) !=
											  UnicodeCategory.NonSpacingMark)
			  ).Normalize(NormalizationForm.FormC);
		}

		#endregion

		
		#region Ajustes

		public static List<string> Split(string pSeparator, string pValue, char? pGroupValueLed = null, bool pTrim = true)
		{
			List<string> result;

			string currentItem;

			int separatorIndex;
			int currentIndex = 0;
			int i = -1;

			result = new List<string>();
			
			if (TextHelper.IsEmpty (pValue))
			{
				return result;
			}

			while ((separatorIndex = pValue.Substring (currentIndex).IndexOf (pSeparator)) != -1)
			{
				currentItem = pValue.Substring (currentIndex, separatorIndex);

				if (pTrim)
				{
					currentItem = currentItem.Trim ();
				}

				result.Add (currentItem);

				currentIndex += separatorIndex + pSeparator.Length;
			}

			if (currentIndex < pValue.Length)
			{
				currentItem = pValue.Substring (currentIndex);

				if (pTrim)
				{
					currentItem = currentItem.Trim ();
				}

				result.Add (currentItem);
			}


			// Viene algo como C=CO, L="BOGOTÁ, D.C.", X=098
			// La idea es tener los valores entre "" como uno solo no partido
			if (pGroupValueLed != null)
			{
				try
				{
					for (i = 0; i < result.Count; i++)
					{
						// Se fusiona con el siguiente si lo hay
						if (i > 0 
							&& result[i].Length > 0
							&& result[i].Last() == pGroupValueLed 
							&& result[i - 1].Contains (pGroupValueLed.ToString ()))
						{
							result [i - 1] += pSeparator + result [i];

							result.RemoveAt (i);

							i--;
						}
					}
				}
				catch (Exception pEx)
				{
					pEx.Data.Add ("pSeparator", pSeparator);
					pEx.Data.Add ("pValue", pValue);
					pEx.Data.Add ("pGroupValueLed", pGroupValueLed);
					pEx.Data.Add ("pTrim", pTrim);
					pEx.Data.Add("i", i);
					pEx.Data.Add("currentIndex", currentIndex);

					throw new Exception ("Error Spliting as Dictionary", pEx);
				}
			}

			return result;
		}


		//public static Dictionary<string, string> Split (string pValue, string pPairSeparator, char pKeyValueSeparator)
		//{
		//    Dictionary<string, string> result;

		//    int indexKeyValueSeparator;

		//    string key;
		//    string value;


		//    result = new Dictionary<string,string> ();

		//    if (!IsEmpty (pValue))
		//    {
		//        foreach (string item in Split(pPairSeparator, pValue, pGroupValueLed, pTrim))
		//        {
		//            indexKeyValueSeparator = item.IndexOf(pKeyValueSeparator);

		//            if (indexKeyValueSeparator == -1)
		//            {
		//                break;
		//            } 
					
		//            key = item.Substring(0, indexKeyValueSeparator).Trim();

		//            if (!IsEmpty(key))
		//            {
		//                if (!result.ContainsKey(key))
		//                {
		//                    if (indexKeyValueSeparator <= item.Length)
		//                    {
		//                        value = item.Substring(indexKeyValueSeparator + 1);
		//                    }
		//                    else
		//                    {
		//                        value = string.Empty;
		//                    }


		//                    result.Add(key, value);
		//                }
		//            }
		//        }
		//    }

		//    return result;
		//}


		public static Dictionary<string, string> Split(string pValue, string pPairSeparator, char pKeyValueSeparator, char? pGroupValueLed = null, bool pTrim = true)
		{
			int pLastRightIndexValueReaded;


			return Split(pValue, pPairSeparator, pKeyValueSeparator, out pLastRightIndexValueReaded, pGroupValueLed, pTrim);
		}


		public static Dictionary<string, string> Split(string pValue, string pPairSeparator, char pKeyValueSeparator, out int pLastRightIndexValueReaded, char? pGroupValueLed = null, bool pTrim = true)
		{
			Dictionary<string, string> result;

			int indexKeyValueSeparator;

			string key;
			string value;


			result = new Dictionary<string, string>();

			pLastRightIndexValueReaded = 0;


			if (!IsEmpty(pValue))
			{
				foreach (string item in Split (pPairSeparator, pValue, pGroupValueLed, pTrim))
				{
					indexKeyValueSeparator = item.IndexOf (pKeyValueSeparator);

					if (indexKeyValueSeparator == -1)
					{
						break;
					}


					key = item.Substring (0, indexKeyValueSeparator).Trim ();

					if (!IsEmpty(key))
					{
						if (!result.ContainsKey(key))
						{
							if (indexKeyValueSeparator <= item.Length)
							{
								value = item.Substring (indexKeyValueSeparator + 1);

								pLastRightIndexValueReaded = indexKeyValueSeparator + value.Length;
							}
							else
							{
								value = string.Empty;
							}
							

							result.Add(key, value.Trim ());
						}
					}
				}
			}

			return result;
		}


		public static List<string> Split (char pSeparator, string pValues)
		{
			List<string> result = new List<string> ();


			if (IsEmpty (pValues))
			{
				return result;
			}

			result = new List<string> ();

			foreach (string val in pValues.Trim ().Split (pSeparator))
			{
				if (!IsEmpty (val))
				{
					result.Add (val.Trim ());
				}
			}

			return result;
		}
		
		
		public static List<string> SplitLines(string pCommandSQL, string pSentence, bool pRemoveEmptyLines = true)
		{
			List<string> result;
			
			
			result = new List<string> (Regex.Split (pCommandSQL, string.Format (@"\b{0}\b", pSentence), RegexOptions.IgnoreCase));
			
			if (pRemoveEmptyLines)
			{
				result.RemoveAll (i => IsEmpty (i));
			}
			
			return result;
		}
		
		#endregion
		
		
		#region Conversion de Listas
		
		public static List<int> ConvertoToIntList (List<string> pList)
		{
			List<int> result = new List<int> ();


			if (DataHelper.IsEmpty (pList)) { return null; }
			
			foreach (string val in pList)
			{
				result.Add (GetInt (val));
			}

			return result;
		}


		public static string ToString<A, B> (Dictionary<A, B> pItems, string pKeyValueSeparator = "\n") 
		{
			StringBuilder result;


			if (DataHelper.IsEmpty (pItems))
			{
				return string.Empty;
			}

			result = new StringBuilder();

			foreach (KeyValuePair<A, B> item in pItems)
			{
				result.Append (string.Format ("{0} = {1}{2}", item.Key, item.Value, pKeyValueSeparator));
			}

			return result.ToString ();
		}


		public static string ToString<O> (string pSeparator, IList<O> pList)
		{
			StringBuilder result;


			if (DataHelper.IsEmpty (pList)) { return string.Empty; }
			

			result = new StringBuilder ();

			foreach (O item in pList)
			{
				result.Append (item.ToString () + pSeparator);
			}

			result.Length -= pSeparator.Length;

			return result.ToString ();
		}


		public static string ToString<O>(string pSeparator, params O [] pList)
		{
			StringBuilder result;


			if (DataHelper.IsEmpty(pList)) { return string.Empty; }


			result = new StringBuilder();

			foreach (O item in pList)
			{
				result.Append(item.ToString() + pSeparator);
			}

			result.Length -= pSeparator.Length;

			return result.ToString();
		}
		
		#endregion
		
		
		#region Busquedas

		public static bool IsIn(string pValue, List<string> pValues, bool pResultIfEmptyList = false)
		{
			if (DataHelper.IsEmpty (pValues)) 
			{
				return pResultIfEmptyList; 
			}

			return pValues.Exists (i => string.Compare (i, pValue, true) == 0);
		}


		public static bool IsIn (string pValue, params string [] pValues)
		{
			return IsIn (pValue, false, pValues);
		}


		public static bool IsIn (string pValue, bool pResultIfEmptyList, params string [] pValues)
		{
			if (DataHelper.IsEmpty (pValues)) 
			{
				return pResultIfEmptyList; 
			}

			foreach (string item in pValues)
			{
				if (string.Compare (item, pValue, true) == 0)
				{
					return true;
				}
			}

			return false;
		}

		#endregion


		#region Presentacion
		
		public static string ConcatSepIfValueNotEmpty (string pTitle, string pValue, string pSeparator)
		{
			if (pValue == null) { return string.Empty; }
			
			return ConcatIfValueNotEmpty (pTitle, pValue) + pSeparator;
		}


		public static string ConcatSepIfValueNotEmpty (string pTitle, int? pValue, string pSeparator)
		{
			if (pValue == null) { return string.Empty; }
			
			return ConcatIfValueNotEmpty (pTitle, pValue.Value.ToString ()) + pSeparator;
		}
		
		
		public static string ConcatSepDateIfValueNotEmpty (string pTitle, DateTime? pValue, string pSeparator)
		{
			if (pValue == null) { return string.Empty; }
			
			return ConcatIfValueNotEmpty (pTitle, pValue.Value.ToString ("yyyy-MM-dd")) + pSeparator;
		}


		public static string ConcatSepLongDateIfValueNotEmpty (string pTitle, DateTime? pValue, string pSeparator)
		{
			if (pValue == null) { return string.Empty; }
			
			return ConcatIfValueNotEmpty (pTitle, pValue.Value.ToString ("MMMM dd, yyyy")) + pSeparator;
		}
		
		
		public static string ConcatSepIfValueNotEmptyName (string pTitle, BasicReference pBasRef, string pSeparator)
		{
			if (pBasRef == null || string.IsNullOrEmpty (pBasRef.Name)) { return string.Empty; }
			
			return pTitle + pBasRef.Name + pSeparator;
		}



		public static string ConcatIfValueNotEmpty (string pTitle, int? pValue)
		{
			if (pValue == null) { return string.Empty; }
			
			return ConcatIfValueNotEmpty (pTitle, pValue.Value.ToString ());
		}
		
		
		public static string ConcatDateIfValueNotEmpty (string pTitle, DateTime? pValue, string pFormat)
		{
			if (pValue == null) { return string.Empty; }
			
			return ConcatIfValueNotEmpty (pTitle, pValue.Value.ToString (pFormat));
		}
		

		public static string ConcatIfValueNotEmptyName (string pTitle, List<BasicReference> pBasRefs)
		{
			StringBuilder result;


			if (pBasRefs == null || pBasRefs.Count == 0) { return string.Empty; }

			result = new StringBuilder (pTitle);

			foreach (BasicReference br in pBasRefs)
			{
				result.Append (br.Name);
				result.Append (", ");
			}

			result.Length -= 2;

			return result.ToString ();
		}


		public static string ConcatIfValueNotEmptyName (string pTitle, BasicReference pBasRef)
		{
			if (pBasRef == null || string.IsNullOrEmpty (pBasRef.Name)) { return string.Empty; }
			
			return pTitle + pBasRef.Name;			
		}


		public static string FormatIfValueNotEmpty (string pFormat, params object [] pValues)
		{
			if (pValues == null || pValues.Length == 0 || pValues [0] == null) { return string.Empty; }

			return string.Format (pFormat, pValues);
		}


		public static string FormatIfValueNotEmpty (string pFormat, params string [] pValues)
		{
			if (pValues == null || pValues.Length == 0 || IsEmpty (pValues [0])) { return string.Empty; }

			return string.Format (pFormat, pValues);
		}


		public static Dictionary<string, string> ConvertToDic (params string [] pKeyValues)
		{
			Dictionary <string, string> result;


			if (DataHelper.IsEmpty (pKeyValues)) { return null; }

			result = new Dictionary<string,string> ();

			for (int i = 0; i < pKeyValues.Length; i += 2)
			{
				result.Add (pKeyValues [i], pKeyValues [i + 1]);
			}

			return result;
		}


		public static string ConcatSortedKeysIfValuesNotEmpty 
		(
			string pSortedKeysSeparatedByX, char pX, bool pUseFirstCapitalLetter, string pPairRightSeparator, params string [] pKeyValues
		)
		{
			List<string> keys;

			Dictionary<string, string> keyValues;

			StringBuilder result;


			if (IsEmpty (pSortedKeysSeparatedByX)) { return string.Empty; }


			keys = new List<string> (pSortedKeysSeparatedByX.Split (pX));

			result = new StringBuilder ();

			keyValues = ConvertToDic (pKeyValues);

			foreach (string key in keys)
			{
				if (keyValues.ContainsKey (key.Trim ()))
				{
					if (!IsEmpty (keyValues [key.Trim ()]))
					{
						if (pUseFirstCapitalLetter)
						{
							result.Append (key.Trim ().ToUpper () [0] + ". ");
						}
						else
						{
							result.Append (key.Trim () + ": ");
						}

						result.Append (keyValues [key.Trim ()] + pPairRightSeparator);
					}					
				}
			}

			return result.ToString ();
		}
		
		
		public static string ConcatIfValuesNotEmpty (string pPairRightSeparator, params string [] pKeyValues)
		{
			StringBuilder result;
			
		
			if (DataHelper.IsEmpty (pKeyValues) || pKeyValues.Length % 2 != 0) { return string.Empty; }
			
			result = new StringBuilder ();
			
			for (int i = 0; i < pKeyValues.Length; i+=2)
			{
				if (!string.IsNullOrEmpty (pKeyValues [i + 1]))
				{
					result.Append (pKeyValues [i] + pKeyValues [i + 1] + pPairRightSeparator);
				}
			}
			
			return result.ToString ();
		}
		
		
		public static string ConcatIfValueMayusThanZero (string pTitle, int pValue)
		{
			if (pValue <= 0) { return string.Empty; }
		
			return ConcatIfValueNotEmpty (pTitle, pValue.ToString ());
		}
		
		
		public static string ConcatIfValueMayusThanZero (string pTitle, int? pValue)
		{
			if (pValue == null) { return string.Empty; }
		
			return ConcatIfValueMayusThanZero (pTitle, pValue.Value);
		}
		
		
		public static string ConcatIfValueNotEmpty (string pTitle, string pValue)
		{
			return ConcatIfValueNotEmpty (pTitle, pValue, string.Empty);
		}
		
		
		public static string ConcatIfValueNotEmpty (string pTitle, string pValue, string pDefaultResultIfEmptyValue)
		{
			if (IsEmpty (pValue))
			{
				return pDefaultResultIfEmptyValue;
			}
			
			return pTitle + pValue;
		}
		
		#endregion


		#region Encoding

		public static Encoding GetFileEncoding(string pFilename)
		{
			try
			{
				using (StreamReader fs = new StreamReader (pFilename, true))
				{
					while (fs.Peek () >= 0)
					{
						fs.Read ();

						return fs.CurrentEncoding;
					}
				}

				throw new GenericInfoException (string.Format ("El archivo {0} esta vacio", pFilename)) { RelatedFilename = pFilename };
			}
			catch (IOException pEx)
			{
				Log.Error (pEx);
			}

			// Se da en casos que el archivo realmente ya no existe por lo cual no importa si llega este valor
			return Encoding.UTF8;
		}

		private static bool IsUTF8Bytes(byte[] data)
		{
			int charByteCounter = 1;　 
			byte curByte; 
			for (int i = 0; i < data.Length; i++)
			{
				curByte = data[i];
				if (charByteCounter == 1)
				{
					if (curByte >= 0x80)
					{
						while (((curByte <<= 1) & 0x80) != 0)
						{
							charByteCounter++;
						}
                    　
						if (charByteCounter == 1 || charByteCounter > 6)
						{
							return false;
						}
					}
				}
				else
				{
					if ((curByte & 0xC0) != 0x80)
					{
						return false;
					}
					charByteCounter--;
				}
			}
			if (charByteCounter > 1)
			{
				throw new Exception("Error byte format");
			}
			return true;
		}

		#endregion


		#region Lectura CSV

		public static List<T> GetListFromCSVFile<T> (string pFilename, bool pFirstRowIsHeader, char pSeparator) where T : new ()
		{
			try
			{
				return GetListFromCSVFile <T> (System.IO.File.OpenText (pFilename), pFirstRowIsHeader, pSeparator);
			}
			catch (Exception pEx)
			{
				throw new GenericException (string.Format ("The file {0} cannot be readed as CSV", pFilename), pEx);
			}
		}


		// TODO: Permitir sacarlo como una tabla de un tipo T o como un listado de un tipo T
		public static List<T> GetListFromCSVFile<T> (TextReader pReader, bool pFirstRowIsHeader, char pSeparator) where T : new ()
		{
			MemberInfo memberInfo;

			PropertyInfo [] propertiesOfT;

			List<T> result;

			T item;

			List<ColumnAttribute> columns;
			ColumnAttribute currentColumn;

			string currentLine;
			string [] currentLineParts;
			

			memberInfo = typeof (T);

			result = new List<T> ();

			propertiesOfT = typeof (T).GetProperties ();
			
			columns = new List<ColumnAttribute> ();

			foreach (PropertyInfo property in propertiesOfT)
			{
			    currentColumn = Attribute.GetCustomAttribute (property, typeof (ColumnAttribute), false) as ColumnAttribute;
				
				currentColumn.SeteableProperty = property;

				if (currentColumn != null)
				{
					columns.Add (currentColumn);
				}
			}

			
			try
			{
				// Se omite la primer fila
				if (pFirstRowIsHeader)
				{
					pReader.ReadLine ();
				}

				while ((currentLine = pReader.ReadLine ()) != null)
				{
					item = new T ();

					currentLineParts = currentLine.Split (pSeparator);

					if (currentLineParts.Length < columns.Count)
					{
						throw new GenericInfoException (string.Format ("Hay menos columnas para leer que las requeridas: {0} vs {1}", currentLineParts.Length, columns.Count));
					}
					
					foreach (ColumnAttribute col in columns)
					{
						if (!string.IsNullOrEmpty (col.DateFormat))
						{
							col.SeteableProperty.SetValue (item, TextHelper.GetNullableDateTime (currentLineParts [col.ColumnOrder], col.DateFormat), null);
						}
						else if (col.IsBool)
						{
							col.SeteableProperty.SetValue (item, TextHelper.GetNullableBool (currentLineParts [col.ColumnOrder]), null);
						}
						else if (col.IsInt)
						{
							col.SeteableProperty.SetValue (item, TextHelper.GetNullableInt (currentLineParts [col.ColumnOrder]), null);
						}
						else
						{
							col.SeteableProperty.SetValue (item, currentLineParts [col.ColumnOrder], null);
						}
					}

					result.Add (item);
				}

				return result;
			}
			catch (Exception)
			{
				throw;
			}
			finally
			{
				pReader.Close ();
			}
		}

		#endregion


		#region Find

		public static bool StartsWithIN (string pSearch, params string [] pINs)
		{
			if (DataHelper.IsEmpty (pINs))
			{
				return false;
			}

			foreach (string sin in pINs)
			{
				if (pSearch.StartsWith (sin, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}

			return false;
		}


		public static bool EndsWithIN (string pSearch, params string [] pINs)
		{
			if (DataHelper.IsEmpty (pINs))
			{
				return false;
			}

			foreach (string sin in pINs)
			{
				if (pSearch.EndsWith (sin, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}

			return false;
		}


		public static bool ContainsIN (string pSearch, params string [] pINs)
		{
			if (DataHelper.IsEmpty (pINs))
			{
				return false;
			}

			foreach (string sin in pINs)
			{
				if (pSearch.IndexOf (sin, StringComparison.OrdinalIgnoreCase) != -1)
				{
					return true;
				}
			}

			return false;
		}

		#endregion


		#region Text Secuences

		public static long? GetAsNumber (string pValue)
		{
			long result;

			
			StringBuilder sb = new StringBuilder ();

			for (int i = 0; i< pValue.Length; i++)
			{
				if (char.IsDigit (pValue [i]))
				{
					sb.Append (pValue[i]);
				}
			}

			if (!long.TryParse (sb.ToString (), out result))
			{
				return null;
			}

			return result;
		}


		public static bool? IsTextNumericSecuenced (params string [] pValues)
		{
			long? previous = null;


			if (DataHelper.IsEmpty (pValues) || pValues.Count () == 1) { return null; }


			foreach (long? item in (from V in pValues select GetAsNumber (V)))
			{
				if (item == null || (previous != null && item != previous.Value + 1))
				{
					return false;
				}

				previous = item;
			}

			return true;
		}

		#endregion


		#region Read file

		public static Dictionary<string, string> Split (Stream pStream, string pKeyValueSeparator, char pKeySeparator)
		{
			string currentKey = string.Empty;

			char currentChar;

			string currentValue = string.Empty;

			bool isReadingKey = true;

			Dictionary<string, string> result;

			int currentRead;


			result = new Dictionary<string,string> ();

			if (pStream == null) { return result; }


			while ((currentRead = pStream.ReadByte ()) != -1)
			{
				currentChar = Convert.ToChar (currentRead);

				if (currentChar == ':' && isReadingKey)
				{
					isReadingKey = false;

					currentValue = string.Empty;
				}
				else
				{
					if (isReadingKey)
					{
						currentKey += currentChar;
					}
					else
					{
						currentValue += currentChar;
					}
				}

				if (currentValue.EndsWith (pKeyValueSeparator))
				{
					currentValue = currentValue.Substring (0, currentValue.Length - pKeyValueSeparator.Length);

					result.Add (currentKey.Trim (), currentValue.Trim ());

					currentKey = string.Empty;

					isReadingKey = true;
				}
				else if (currentKey.EndsWith (pKeyValueSeparator))
				{
					pStream.Position -= currentKey.Length;

					break;
				}
			}


			return result;
		}


		public static IEnumerable<string> ReadLines (string pFileName)
		{
			StringBuilder currentLine = new StringBuilder ();
			int currentRead;
			char? currentCharRead = null;


			using (StreamReader reader = new StreamReader(pFileName, Encoding.Default, true))
			{
				while (reader.Peek () >= 0)
				{
					currentRead = reader.Read();

					currentCharRead = (char) currentRead;
					
					// Es retorno de carro CRLF este \n es LF
					if (currentCharRead == Environment.NewLine [1])
					{
						yield return currentLine.ToString ();
						
						currentLine.Clear ();
					}
					// Del CRLF el CR se omite
					else if (currentCharRead != Environment.NewLine [0])
					{
						currentLine.Append (currentCharRead);
					}
				}

				// Si el archivo tiene su "ultima" linea con CRLF es como si tuviera una linea mas
				if (currentCharRead != null && (currentCharRead == Environment.NewLine[0] || currentCharRead == Environment.NewLine[1]))
				{
					yield return string.Empty;
				}
				else
				{
					yield return currentLine.ToString ();
				}
			}
		}

		#endregion


		#region SINO

		public static string ToVERDADEROFALSO (bool? pValue)
		{
			if (pValue == null) { return string.Empty; }

			if (pValue.Value)
			{
				return "VERDADERO";
			}

			return "FALSO";
		}


		public static string ToTRUEFALSE(bool? pValue)
		{
			if (pValue == null) { return string.Empty; }

			if (pValue.Value)
			{
				return "TRUE";
			}

			return "FALSE";
		}


		public static string ToSINO (bool? pValue)
		{
			if (pValue == null) { return string.Empty; }

			if (pValue.Value)
			{
				return "SI";
			}

			return "NO";
		}

		#endregion


		#region Datetime

		public static string DateTimeNowStringCommon
		{
			get
			{
				return DateTime.Now.ToString ("yyyy-MM-dd hh:mm:ss tt");
			}
		}


		public static string DateTimeNowStringMilitar
		{
			get
			{
				return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
			}
		}


		public static string DateNowString
		{
			get
			{
				return DateTime.Now.ToString("yyyy-MM-dd");
			}
		}

		#endregion


		#region Email

		public static bool IsEmail (string pValue)
		{
			return (!string.IsNullOrWhiteSpace (pValue) && Regex.IsMatch (pValue, REGEX_Email));
		}

		#endregion
	}
}